import datetime

from flask import request
from flask_restful import fields, Resource, abort
from flask_restful.fields import Raw

from main.apis.api_constant import HTTP_OK
from main.apis.user.utils import ordinary_login_required, get_user_id, get_now_time
from main.ext import cache, db
from main.models.goods.goods_model import Goods
from main.models.user.user_model import CartModel, OrderModel, OrderGoodsModel
from main.settings import SERVER_HOST


class CartGoodCount(Raw):
    def format(self, value):
        user_id = get_user_id()
        cart_good = CartModel.query.filter_by(c_user_id=user_id, c_goods_id=value)
        return cart_good.c_goods_count


good_fields = {
    'name': fields.String(attribute='g_name'),
    'price': fields.Float(attribute='g_price'),
    'count': CartGoodCount(attribute='g_id')
}

order_fields = {
    'price': fields.Float(attribute='o_price'),
    'time': fields.DateTime(attribute='o_time'),
    'is_paid': fields.Boolean(attribute='o_status'),
    # 'goods': fields.List()
}


class OrdersResource(Resource):  # 获取全部订单（有效、无效）信息
    def get(self):
        pass


class OrderResource(Resource):
    @ordinary_login_required
    def get(self):  # 将购物车内选中的所有商品组合生成订单
        user_id = get_user_id()
        cart_goods = CartModel.query.filter_by(c_user_id=user_id, c_is_selected=True).all()
        if not cart_goods:
            abort(403, error='购物车为空，无法生成订单，先去挑几件商品吧')
        price = 0
        result = []

        for cart_good in cart_goods:
            raw_good = cart_good.goods
            good_name = raw_good.g_name
            good_price = raw_good.g_price
            good_count = cart_good.c_goods_count
            g_count = raw_good.g_count - good_count  # 商品库存减去订单商品数量
            if g_count < 0:
                abort(403, error=f'商品库存不足，商品：`{raw_good.g_name}` 现有库存：`{raw_good.g_count}`。')
            raw_good.g_count = raw_good.g_count - good_count
            good_total_price = int(good_price * 100) * good_count  # 将float转为int计算，否则会有精度问题
            result.append({
                'id': cart_good.c_goods_id,
                'name': good_name,
                'price': good_price,
                'count': good_count,
                'total_price': good_total_price / 100
            })
            price += good_total_price
        price /= 100  # price 除以 100 为实际精确价格
        # 写入订单表
        now = get_now_time()[1]
        order = OrderModel()
        order.o_user_id = user_id
        order.o_price = price
        order.o_time = now
        # order.id = ''  # id 可以复杂一些
        order.save()
        # 写入订单商品表
        for good in result:
            order_good = OrderGoodsModel()
            order_good.o_goods_id = good.get('id')
            order_good.o_goods_count = good.get('count')
            order_good.o_order_id = order.id
            # order_good.save()  # 自定义保存函数里每次都要建立一个新的连接，浪费资源，当需要提交多条信息时，需要把save()拆开
            db.session.add(order_good)
        db.session.commit()

        data = {
            'status': HTTP_OK,
            'msg': '已生成订单',
            'id': order.id,
            'price': price,
            'time': now,
            'is_paid': order.o_status,
            'pay_url': f'{SERVER_HOST}pay/{order.id}?token={request.args.get("token", None)}',
            'goods': result,
        }
        return data

    @ordinary_login_required
    def post(self):
        # 限时二十分钟付款(倒计时无法在后端完成，需要在前端用JavaScript才能完成)，成功则用ajax传递成功信息，更改o_status
        # 在这二十分钟内，商品数量锁定(库存商品数量减去订单商品数量)；超时或取消则返回o_valid的NOT_VALID值，库存数量恢复，订单失效。
        # o_valid为NOT_VALID时，订单失效不可支付。为VALID且o_status为NOT_PAID时可支付。为VALID且o_status=PAID时无需支付
        # 以上逻辑也可在前端直接通过当前时间与订单时间差和o_status状态判断订单是否有效, 更为简单
        # 此demo仅为后端demo，所以只能在后端粗略地解决时效问题
        pass
